#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>

//利用递归求某个数字的阶乘

//int Fact(int n)
//{
//	if (n == 0)
//		return 1;
//	else
//	{
//		return n * Fact(n - 1);
//	}
//}
//
//
//
//
//int main()
//{
//	int n = 0;
//	printf("请输入要求阶乘的数字\n");
//	scanf("%d", &n);
//	int ret = Fact(n);
//	printf("%d\n", ret);
//
//	return 0;
//}
//


//利用阶乘顺序打印一个整数的每一位
//例如：输入 1234
//     打印 1 2 3 4

//void Print(int n)
//{
//	if (n > 9)
//	{
//		Print(n / 10);
//	}
//	
//	printf("%d ", n % 10);
//
//}
//
//
//int main()
//{
//	int n = 0;
//	printf("请输入要打印的整数\n");
//	scanf("%d", &n);
//	Print(n);
//	return 0;
//}
/************************************************************
//总结：递归，分为两步，递出去，和归回来                 *****************
//递归在书写的时候，有两个必要条件：                     ****************
// 1.存在限制条件，满足这个限制条件后，递归便不再继续        *************
// 2.每次递归调用之后能够越来越接近这个限制条件            *****************
**************************************************************/


/*

在c语言中每一次函数调用，都需要为本次函数调用在内存的栈区申请一块内存空间来保存函数调用期间
的局部变量的值，这块空间被成为运行时堆栈，或者函数栈帧

函数不返回，函数对应的栈帧空间就一直占用，所以如果函数调用中存在递归调用的话，每一次递归函数调用都会开辟
自己的栈帧空间，直到函数递归不再继续，开始回归，才逐层释放栈帧空间。

所以如果采用函数递归的方式完成代码，递归层次太深，就会浪费太多的战阵空间，也就有可能出现栈溢出的情况

所以如果不想使用递归，就要用其他的办法，迭代（循环）就是常用的方法
*/
//例如
// 在求n的阶乘的时候，也是可以产生1~n个数字累计乘在一起的

//int Fact(int n)
//{
//	int i = 0;
//	int ret = 1;
//	for (i = 1; i <= n; i++)
//	{
//		ret *= i;
//	}
//	return ret;
//}
//
//
//
//
//int main()
//{
//	int n = 0;
//	scanf("%d", &n);
//	int ret = Fact(n);
//	printf("%d\n", ret);
//	return 0;
//}
//上面这个例子，使用迭代的方法就比递归的效率高的多



/*
事实上，许多的问题都是以递归的形式解释的，只是因为它比非递归的形式更加清晰，但是，这些问题实际上用迭代的方法是比递归更加高效的

当一个问题特别复杂的时候，难以使用迭代的方法实现的时候，递归的简洁清晰性就可以弥补它运行时候所带来的开销
*/

//例：求第N个斐波那契数

//int Fib(int n)
//{
//	if (n <= 2)
//	{
//		return 1;
//	}
//	else
//	{
//		return Fib(n - 1) + Fib(n - 2);
//	}
//}
//
//int main()
//{
//	int n = 0;
//	scanf("%d", &n);
//	int ret = Fib(n);
//	printf("%d\n", ret);
//	return 0;
//}

//当n输入50的时候，就需要很长的时间算出结果，说明递归的算法是十分低效的，为什么呢？？？
//其实递归程序会不断的展开，即把大的复杂的问题展开成小的，简单的问题来解决，但在展开过程中，递归的过程就会产生重复计算
//并且，递归的层次越深，冗余计算也就会越多

//可以做如下测试
//int count = 0;
//int Fib(int n)
//{
//	
//	if (n == 3)
//		count++;
//	if (n <= 2)
//	{
//		return 1;
//	}
//	else
//	{
//		return Fib(n - 1) + Fib(n - 2);
//	}
//}
//
//int main()
//{
//	int n = 0;
//	scanf("%d", &n);
//	int ret = Fib(n);
//	printf("%d\n", ret);
//	printf("count 3 = %d\n", count);
//	return 0;
//}
//可以看出，在算第40个斐波那契数的时候，fib（3）被重复计算了多次，导致冗余



//可以用迭代的方法实现

//int Fib(int n)
//{
//	int a = 1;
//	int b = 1;
//	int c = 1;
//	while(n > 2)
//	{
//		c = a + b;
//		a = b;
//		b = c;
//		n--;
//	}
//	return  c;
//}
//
//int main()
//{
//	int n = 0;
//	scanf("%d", &n);
//	int ret = Fib(n);
//	printf("%d\n", ret);
//	return 0;
//}

//迭代实现这个代码，效率就会高很多了！！！

//所以递归虽好，不要迷恋！！！

//拓展练习
//1.青蛙跳台阶问题
//2.汉诺塔问题
//3.了解尾递归，尝试用尾递归求斐波那契数